using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using ZeroSum.App.Datas;
using ZeroSum.Exceptions;
using ZeroSum.Models;

namespace ZeroSum.App.Middlewares;

/// <summary>
///     异常全局处理的中间件
/// </summary>
public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionHandlerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception e)
        {
            await HandleException(context, e);
        }
    }

    private async Task HandleException(HttpContext context, Exception exception)
    {
        var response = context.Response;
        response.StatusCode = 200;
        response.ContentType = "application/json";

        var text = GetResponseText(exception);
        await response.WriteAsync(text);
    }

    private string GetResponseText(Exception exception)
    {
        var data = "";

        switch (exception)
        {
            case ValidateFailedException ex:
                var res = ApiResponse<IList<string>>.Of(ex.Status, ex.Message, ex.Errors);
                data = Serialize(res);
                break;
            case BusinessException ex:
                data = Serialize(ApiResponse<string>.Of(ex.Status, ex.Message, ex.ToString()));
                break;
            case CustomException ex :
                data = Serialize(ApiResponse<string>.Of(ex.Code, ex.Message, ex.ToString()));
                break;
            default:
                data = Serialize(ApiResponse<string>.Of(ResponseStatus.Error, exception.Message,
                    exception.ToString()));
                break;
        }

        return data;
    }

    private static string Serialize<T>(T data)
    {
        var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
        return JsonSerializer.Serialize(data, options);
    }
}

public static class ExceptionHandlerMiddlewareExtensions
{
    /// <summary>
    ///     启用全局异常处理（模型验证也会处理）
    /// </summary>
    /// <param name="app"></param>
    /// <returns></returns>
    public static IApplicationBuilder EnableExceptionHandler(this IApplicationBuilder app)
    {
        app.UseMiddleware<ExceptionHandlerMiddleware>();
        return app;
    }
}